import scrapy


class DangSpider(scrapy.Spider):
	name = 'dang'
	# 有多页下载任务，尽量不添加 协议 和 www，这样才能进入其他页面
	allowed_domains = ['category.dangdang.com']
	# 如果 url 指向的是一个 html 页面，否则以 .html 结尾的，需要去掉后面的 “/”
	start_urls = ['http://category.dangdang.com/cp01.03.56.00.00.00.html']

	# 多页下载的
	# 先确定基本 url 和 第一页
	# 多页下载解决：url 的拼接
	base_url = 'http://category.dangdang.com/pg'
	page = 1

	def parse(self, response):
		# xpath() 返回的 selector 对象可以再次调用 xpath()、css()方法
		# 也就是说，在编写 xpath() 查询规则时，不用精准写全，而是写多个元素共同的 上级元素
		# 用处：有些网站有“懒加载”设置，当网页没有下拉加载完成时，有些标签的属性 与 网页下拉后全部加载完成时标签的属性 不同。
		# 如果 规则 写全、写精准，那么有时爬取的数据不全，因为标签的属性改变了

		# src_list  //ul[@id='component_59']/li/a/img/@src
		# name_list  //ul[@id='component_59']/li/a/img/@alt
		# price_list  //ul[@id='component_59']/li/p[@class='price']/span[1]

		# 这个不用准确定位，只用来确定循环次数，因为所想要获取的数据均在 li 元素之下
		# li 元素就是几个 元素共同的上级
		li_list = response.xpath("//ul[@id='component_59']/li")

		# 因为 parse() 最后的返回值必须是 可迭代对象，所以创建一个空列表来存入数据
		# book_list = []
		# 因为有 yield 生成器，所以可以不需要这个列表（迭代器）了

		# 有共有的 selector 对象时，可以再调用 xpath()、css
		# 所以直接遍历列表中的 selector 对象
		for li in li_list:
			# ./ 表示从当前目录开始
			name = li.xpath("./a/img/@alt").extract_first()
			price = li.xpath("./p[@class='price']/span[1]").extract_first()

			# 此时注意：这个网站的图片属性“懒加载”，当图片全部下拉加载完时与没加载完的属性有所不同
			# 而且，懒加载没有加载完时，只能获取到第一本书的图片，当懒加载加载完后，第一本书的图片 src 又获取不到
			# 所以需要对图片 src 进行判断，给予不同的 查询规则
			# 通过观察网站发现，当图片没有加载完时，图片的真实地址属性为：data-original
			# 而已经加载完的图片，如第一张图片的真实地址属性为：src
			src = li.xpath("./a/img/@data-original").extract_first()

			if src:
				src = src
			else:
				src = li.xpath("./a/img/@src").extract_first()

			# 将数据存入字典中
			book = {}

			book['name'] = name
			book['src'] = src
			book['price'] = price

			# 将数据添加到列表中

			# return 是一次性将这个列表全部返回给 管道
			# 如果数据过大，则消耗内存，浪费资源，所以使用 yield 可以更加节省内存
			# return book_list
			# yield 会记录返回的位置，再次返回结果时，会直接从下一个位置（遍历的下一个元素）返回
			# 注意，yield 在 for 循环里，表示遍历一个数据就返回一个数据，不用等全部遍历完再一次性返回
			yield book

		if self.page < 100:
			self.page = self.page + 1
			url = self.base_url + str(self.page) + '-cp01.03.56.00.00.00.html'
			# 生成 请求对象，提交给 引擎，引擎再提交给 调度器生成队列，等待下载器向服务器请求下载
			yield scrapy.Request(url=url, callback=self.parse)
